package io.aicn.lowcode.generator.independent.constant;

public class CodeTemplates {

    // Entity 模板
    public static final String ENTITY_TEMPLATE = """
        package ${entity.packageName};

        import lombok.Data;
        import java.io.Serializable;
        import java.util.Date;
        #if(${entity.swagger})
        import io.swagger.v3.oas.annotations.media.Schema;
        #end

        #if(${entity.swagger})
        @Schema(description = "${entity.tableComment}")
        #end
        @Data
        public class ${entity.className} implements Serializable {
            #if(${entity.serialVersionUID})
            private static final long serialVersionUID = 1L;
            #end

            #foreach($field in ${fields})
            #if(${entity.swagger})
            @Schema(description = "${field.comment}")
            #end
            private ${field.javaType} ${field.javaProperty};
            
            #end
        }
        """;

    // Mapper 接口模板
    public static final String MAPPER_INTERFACE_TEMPLATE = """
        package ${mapper.packageName};

        import ${entity.packageName}.${entity.className};
        import org.apache.ibatis.annotations.Mapper;
        import org.apache.ibatis.annotations.Param;
        import java.util.List;

        @Mapper
        public interface ${mapper.className} {
            
            /**
             * 插入记录
             */
            int insert(${entity.className} entity);
            
            /**
             * 根据ID删除记录
             */
            int deleteById(${primaryKey.javaType} ${primaryKey.javaProperty});
            
            /**
             * 根据ID更新记录
             */
            int updateById(${entity.className} entity);
            
            /**
             * 根据ID查询记录
             */
            ${entity.className} selectById(${primaryKey.javaType} ${primaryKey.javaProperty});
            
            /**
             * 查询所有记录
             */
            List<${entity.className}> selectAll();
            
            /**
             * 根据条件查询记录
             */
            List<${entity.className}> selectByCondition(${entity.className} entity);
            
            /**
             * 分页查询记录
             */
            List<${entity.className}> selectPage(@Param("offset") int offset, @Param("limit") int limit);
            
            /**
             * 查询记录总数
             */
            int selectCount(${entity.className} entity);
        }
        """;

    // Mapper XML 模板
    public static final String MAPPER_XML_TEMPLATE = """
        <?xml version="1.0" encoding="UTF-8" ?>
        <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
        <mapper namespace="${mapper.packageName}.${mapper.className}">
            
            <resultMap id="BaseResultMap" type="${entity.packageName}.${entity.className}">
                #foreach($field in ${fields})
                <id column="${field.name}" property="${field.javaProperty}" #if(${field.primaryKey})#end/>
                #end
            </resultMap>
            
            <sql id="Base_Column_List">
                #foreach($field in ${fields})
                #if($foreach.count > 1), #end${field.name}
                #end
            </sql>
            
            <insert id="insert" parameterType="${entity.packageName}.${entity.className}" 
                    #if($primaryKey.autoIncrement)useGeneratedKeys="true" keyProperty="$primaryKey.javaProperty"#end>
                INSERT INTO ${mapper.tableName} (
                #foreach($field in ${fields})
                #if($foreach.count > 1), #end${field.name}
                #end
                ) VALUES (
                #foreach($field in ${fields})
                #if($foreach.count > 1), #end#{${field.javaProperty}}
                #end
                )
            </insert>
            
            <delete id="deleteById">
                DELETE FROM ${mapper.tableName} WHERE ${primaryKey.name} = #${primaryKey.javaProperty}
            </delete>
            
            <update id="updateById" parameterType="${entity.packageName}.${entity.className}">
                UPDATE ${mapper.tableName}
                SET
                #foreach($field in ${fields})
                #if(!$field.primaryKey)
                #if($foreach.count > 1), #end${field.name} = #{${field.javaProperty}}
                #end
                #end
                WHERE ${primaryKey.name} = #${primaryKey.javaProperty}
            </update>
            
            <select id="selectById" resultMap="BaseResultMap">
                SELECT <include refid="Base_Column_List"/>
                FROM ${mapper.tableName}
                WHERE ${primaryKey.name} = #${primaryKey.javaProperty}
            </select>
            
            <select id="selectAll" resultMap="BaseResultMap">
                SELECT <include refid="Base_Column_List"/>
                FROM ${mapper.tableName}
                ORDER BY ${primaryKey.name} DESC
            </select>
            
            <select id="selectByCondition" resultMap="BaseResultMap">
                SELECT <include refid="Base_Column_List"/>
                FROM ${mapper.tableName}
                <where>
                    #foreach($field in ${fields})
                    <if test="${field.javaProperty} != null">
                        AND ${field.name} = #{${field.javaProperty}}
                    </if>
                    #end
                </where>
                ORDER BY ${primaryKey.name} DESC
            </select>
            
            <select id="selectPage" resultMap="BaseResultMap">
                SELECT <include refid="Base_Column_List"/>
                FROM ${mapper.tableName}
                ORDER BY ${primaryKey.name} DESC
                LIMIT #{offset}, #{limit}
            </select>
            
            <select id="selectCount" resultType="int">
                SELECT COUNT(*)
                FROM ${mapper.tableName}
                <where>
                    #foreach($field in ${fields})
                    <if test="${field.javaProperty} != null">
                        AND ${field.name} = #{${field.javaProperty}}
                    </if>
                    #end
                </where>
            </select>
            
        </mapper>
        """;

    // Service 接口模板
    public static final String SERVICE_INTERFACE_TEMPLATE = """
        package ${service.packageName};

        import ${entity.packageName}.${entity.className};
        import java.util.List;

        public interface ${service.interfaceName} {
            
            /**
             * 保存记录
             */
            boolean save(${entity.className} entity);
            
            /**
             * 根据ID删除记录
             */
            boolean deleteById(${primaryKey.javaType} ${primaryKey.javaProperty});
            
            /**
             * 根据ID更新记录
             */
            boolean updateById(${entity.className} entity);
            
            /**
             * 根据ID查询记录
             */
            ${entity.className} getById(${primaryKey.javaType} ${primaryKey.javaProperty});
            
            /**
             * 查询所有记录
             */
            List<${entity.className}> list();
            
            /**
             * 根据条件查询记录
             */
            List<${entity.className}> listByCondition(${entity.className} entity);
            
            /**
             * 分页查询记录
             */
            List<${entity.className}> page(int page, int size);
            
            /**
             * 查询记录总数
             */
            int count(${entity.className} entity);
        }
        """;

    // Service 实现类模板
    public static final String SERVICE_IMPL_TEMPLATE = """
        package ${service.packageName}.impl;

        import ${service.packageName}.${service.interfaceName};
        import ${mapper.packageName}.${mapper.className};
        import ${entity.packageName}.${entity.className};
        import org.springframework.beans.factory.annotation.Autowired;
        import org.springframework.stereotype.Service;
        import java.util.List;

        @Service
        public class ${service.className} implements ${service.interfaceName} {
            
            @Autowired
            private ${mapper.className} ${mapper.className?uncap_first};
            
            @Override
            public boolean save(${entity.className} entity) {
                return ${mapper.className?uncap_first}.insert(entity) > 0;
            }
            
            @Override
            public boolean deleteById(${primaryKey.javaType} ${primaryKey.javaProperty}) {
                return ${mapper.className?uncap_first}.deleteById(${primaryKey.javaProperty}) > 0;
            }
            
            @Override
            public boolean updateById(${entity.className} entity) {
                return ${mapper.className?uncap_first}.updateById(entity) > 0;
            }
            
            @Override
            public ${entity.className} getById(${primaryKey.javaType} ${primaryKey.javaProperty}) {
                return ${mapper.className?uncap_first}.selectById(${primaryKey.javaProperty});
            }
            
            @Override
            public List<${entity.className}> list() {
                return ${mapper.className?uncap_first}.selectAll();
            }
            
            @Override
            public List<${entity.className}> listByCondition(${entity.className} entity) {
                return ${mapper.className?uncap_first}.selectByCondition(entity);
            }
            
            @Override
            public List<${entity.className}> page(int page, int size) {
                int offset = (page - 1) * size;
                return ${mapper.className?uncap_first}.selectPage(offset, size);
            }
            
            @Override
            public int count(${entity.className} entity) {
                return ${mapper.className?uncap_first}.selectCount(entity);
            }
        }
        """;

    // Controller 模板
    public static final String CONTROLLER_TEMPLATE = """
        package ${controller.packageName};

        import ${service.packageName}.${service.interfaceName};
        import ${entity.packageName}.${entity.className};
        import io.swagger.v3.oas.annotations.Operation;
        import io.swagger.v3.oas.annotations.tags.Tag;
        import org.springframework.beans.factory.annotation.Autowired;
        import org.springframework.web.bind.annotation.*;
        import java.util.List;

        @RestController
        @RequestMapping("${controller.apiPath}")
        @Tag(name = "${entity.tableComment}管理", description = "${entity.tableComment}相关操作")
        public class ${controller.className} {
            
            @Autowired
            private ${service.interfaceName} ${service.interfaceName?uncap_first};
            
            @PostMapping
            @Operation(summary = "创建${entity.tableComment}", description = "创建新的${entity.tableComment}记录")
            public boolean create(@RequestBody ${entity.className} entity) {
                return ${service.interfaceName?uncap_first}.save(entity);
            }
            
            @DeleteMapping("/{${primaryKey.javaProperty}}")
            @Operation(summary = "删除${entity.tableComment}", description = "根据ID删除${entity.tableComment}记录")
            public boolean delete(@PathVariable ${primaryKey.javaType} ${primaryKey.javaProperty}) {
                return ${service.interfaceName?uncap_first}.deleteById(${primaryKey.javaProperty});
            }
            
            @PutMapping
            @Operation(summary = "更新${entity.tableComment}", description = "更新${entity.tableComment}记录")
            public boolean update(@RequestBody ${entity.className} entity) {
                return ${service.interfaceName?uncap_first}.updateById(entity);
            }
            
            @GetMapping("/{${primaryKey.javaProperty}}")
            @Operation(summary = "获取${entity.tableComment}", description = "根据ID获取${entity.tableComment}记录")
            public ${entity.className} getById(@PathVariable ${primaryKey.javaType} ${primaryKey.javaProperty}) {
                return ${service.interfaceName?uncap_first}.getById(${primaryKey.javaProperty});
            }
            
            @GetMapping
            @Operation(summary = "获取${entity.tableComment}列表", description = "获取所有${entity.tableComment}记录")
            public List<${entity.className}> list() {
                return ${service.interfaceName?uncap_first}.list();
            }
            
            @GetMapping("/page")
            @Operation(summary = "分页获取${entity.tableComment}", description = "分页获取${entity.tableComment}记录")
            public List<${entity.className}> page(@RequestParam(defaultValue = "1") int page,
                                                  @RequestParam(defaultValue = "10") int size) {
                return ${service.interfaceName?uncap_first}.page(page, size);
            }
        }
        """;

    // 单元测试模板
    public static final String SERVICE_TEST_TEMPLATE = """
        package ${service.packageName};

        import ${service.packageName}.impl.${service.className};
        import ${mapper.packageName}.${mapper.className};
        import ${entity.packageName}.${entity.className};
        import org.junit.jupiter.api.Test;
        import org.junit.jupiter.api.extension.ExtendWith;
        import org.mockito.InjectMocks;
        import org.mockito.Mock;
        import org.mockito.junit.jupiter.MockitoExtension;
        import java.util.Arrays;
        import java.util.List;
        import java.util.Optional;

        import static org.junit.jupiter.api.Assertions.*;
        import static org.mockito.ArgumentMatchers.any;
        import static org.mockito.Mockito.*;

        @ExtendWith(MockitoExtension.class)
        class ${service.interfaceName}Test {
            
            @Mock
            private ${mapper.className} ${mapper.className?uncap_first};
            
            @InjectMocks
            private ${service.className} ${service.className?uncap_first};
            
            @Test
            void save_shouldReturnTrueWhenInsertSuccess() {
                // Arrange
                ${entity.className} entity = new ${entity.className}();
                when(${mapper.className?uncap_first}.insert(any(${entity.className}.class))).thenReturn(1);
                
                // Act
                boolean result = ${service.className?uncap_first}.save(entity);
                
                // Assert
                assertTrue(result);
                verify(${mapper.className?uncap_first}).insert(entity);
            }
            
            @Test
            void save_shouldReturnFalseWhenInsertFail() {
                // Arrange
                ${entity.className} entity = new ${entity.className}();
                when(${mapper.className?uncap_first}.insert(any(${entity.className}.class))).thenReturn(0);
                
                // Act
                boolean result = ${service.className?uncap_first}.save(entity);
                
                // Assert
                assertFalse(result);
            }
            
            @Test
            void getById_shouldReturnEntityWhenExists() {
                // Arrange
                ${primaryKey.javaType} id = ${primaryKey.testValue};
                ${entity.className} expected = new ${entity.className}();
                when(${mapper.className?uncap_first}.selectById(id)).thenReturn(expected);
                
                // Act
                ${entity.className} result = ${service.className?uncap_first}.getById(id);
                
                // Assert
                assertEquals(expected, result);
                verify(${mapper.className?uncap_first}).selectById(id);
            }
            
            @Test
            void list_shouldReturnAllEntities() {
                // Arrange
                List<${entity.className}> expected = Arrays.asList(new ${entity.className}(), new ${entity.className}());
                when(${mapper.className?uncap_first}.selectAll()).thenReturn(expected);
                
                // Act
                List<${entity.className}> result = ${service.className?uncap_first}.list();
                
                // Assert
                assertEquals(expected, result);
                verify(${mapper.className?uncap_first}).selectAll();
            }
        }
        """;
}